package com.gooluke.localcache.aop;

import com.gooluke.localcache.annotation.LocalCache;
import com.gooluke.localcache.cache.LocalCacheManager;
import com.gooluke.localcache.utils.SpELUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
@AllArgsConstructor
@Slf4j
public class LocalCacheAspect {

    private final LocalCacheManager cacheManager;

    @Around("@annotation(localCache)")
    public Object cacheMethod(ProceedingJoinPoint joinPoint, LocalCache localCache) throws Throwable {
        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取方法的返回类型
        Class<?> returnType = signature.getReturnType();
        // 获取方法的全路径限定名（包括包名、类名和方法名）
        String methodName = signature.getMethod().toString();
        // 构建缓存键
        String cacheKey = (localCache.key() != null && !localCache.key().isEmpty()) ? SpELUtil.parseSpEl(localCache.key(), joinPoint) : methodName;
        // 尝试从缓存中获取数据
        Object cachedValue = cacheManager.getCache(cacheKey);
        if (cachedValue != null) {
            // 如果缓存中有数据，则直接返回
            return returnType.cast(cachedValue); // 强制转换为方法的返回类型
        } else {
            long timeout = localCache.timeout();
            // 如果没有缓存，则执行目标方法
            Object proceed = joinPoint.proceed();
            // 将结果放入缓存
            if (timeout == 0) {
                cacheManager.addCache(cacheKey, proceed);
            } else {
                cacheManager.addCache(cacheKey, proceed, timeout, localCache.timeUnit());
            }
            return proceed;
        }
    }
}